package com.jsm.tf.net.session.memory;

import com.google.common.collect.Sets;
import com.jsm.tf.entity.User;
import com.jsm.tf.net.session.ISessionManager;
import io.netty.channel.Channel;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

@ConditionalOnProperty(name = "session.manager.type", havingValue = "memory")
@Component
public class MemorySessionManager implements ISessionManager {
    private ConcurrentHashMap<User, Channel> userChannelMap = new ConcurrentHashMap<>();
    private ConcurrentHashMap<Channel, User> channelUserMap = new ConcurrentHashMap<>();
    private ConcurrentHashMap<Long, Set<User>> roomUserMap = new ConcurrentHashMap<>();
    private ConcurrentHashMap<User, Long> userRoomMap = new ConcurrentHashMap<>();


    @Override
    public User getUserByChannel(Channel channel) {
        return channelUserMap.get(channel);
    }

    @Override
    public Channel getChannelByUser(User user) {
        return userChannelMap.get(user);
    }

    @Override
    public void bind(User user, Channel channel) {
        userChannelMap.put(user, channel);
        channelUserMap.put(channel, user);
    }

    @Override
    public void unbind(Channel channel) {
        User user = channelUserMap.get(channel);
        if (user != null) {
            userChannelMap.remove(user);
            channelUserMap.remove(channel);
        }
    }

    @Override
    public void enterRoom(Long roomId, User user) {
        Set<User> users = roomUserMap.get(roomId);
        if (users != null) {
            users.add(user);
        } else {
            roomUserMap.put(roomId, Sets.newHashSet(user));
        }
        userRoomMap.put(user, roomId);
    }

    @Override
    public void leaveRoom(Long roomId, User user) {
        Set<User> users = roomUserMap.get(roomId);
        if (users != null) {
            users.remove(user);
        }
        if (CollectionUtils.isEmpty(users)) {
            roomUserMap.remove(roomId);
        }
        userRoomMap.remove(user);
    }

    @Override
    public Long getRoomId(User user) {
        Long id = userRoomMap.get(user);
        return id;
    }

    @Override
    public Set<User> getRoomUsers(Long roomId) {
        return roomUserMap.get(roomId);
    }
}
